package test.stubs;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

import messages.BaseMessage;
import messages.DeregistrationMessage;
import messages.MessageFactory;
import messages.MessageType;
import messages.elevator.ElevatorStatusMessage;
import messages.registration.ElevatorRegistrationMessage;
import messages.registration.ElevatorRegistrationMessageAck;
import state.group.ElevatorStruct;

import static org.junit.Assert.*;

public class ElevatorStub extends Thread{
    
    private Socket sock;
    public final ElevatorStruct struct = new ElevatorStruct();
    private boolean shouldRespond = true;
    
    public boolean startUp(int port) throws IOException
    {
        shouldRespond = true;
        
        sock = new Socket(InetAddress.getLocalHost(), port);
        
        ElevatorRegistrationMessage mess = new ElevatorRegistrationMessage((byte)0);
        sock.getOutputStream().write(mess.toByteArray());
        
        BaseMessage recv = MessageFactory.readMessage(sock);
        assertEquals(MessageType.ElevatorRegistrationMessageAck, recv.getMessageType());
        ElevatorRegistrationMessageAck ack = (ElevatorRegistrationMessageAck) recv;
        struct.identifier = ack.getClientId();
        
        return true;
    }
    
    @Override
    public void run()
    {
        BaseMessage mess = null;
        
        while (shouldRespond)
        {
            try
            {
                mess = MessageFactory.readMessage(sock);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            
            if (mess.getMessageType().equals(MessageType.ElevatorStatusRequest))
            {
                ElevatorStatusMessage reply = new ElevatorStatusMessage(struct);
                
                try
                {
                    sock.getOutputStream().write(reply.toByteArray());
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            else if (mess.getMessageType().equals(MessageType.DeregistrationMessage))
            {
                synchronized(this)
                {
                    notify();
                    return;
                }
            }
        }
        try
        {
            mess = MessageFactory.readMessage(sock);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        
        if (mess.getMessageType().equals(MessageType.DeregistrationMessage))
        {
            synchronized(this)
            {
                notify();
            }
        }
    }
    
    public void waitForDeregistration()
    {
        shouldRespond = false;
        synchronized (this)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }

    public void deregister() throws IOException, InterruptedException
    {
        DeregistrationMessage mess = new DeregistrationMessage();
        sock.getOutputStream().write(mess.toByteArray());
        
        Thread.sleep(100);
    }
    
}  
